﻿using System;
using System.Collections;
using System.Security;
using NHibernate;
using NHibernate.Criterion;
using Rodunu.Movies.Contracts;
using Rodunu.Movies.Data;
using Rodunu.Movies.Interfaces.User;
using System.Linq;

namespace Rodunu.Movies.Logic.User
{
    public class UserLogic : Repository<Contracts.UserInfo>, IUser
    {
        private ISession _Session;
        private const int SALTSIZE = 5;

        public Contracts.UserInfo GetByUserName(string name, string password)
        {
            //Verify Password
            ISessionFactory sessionFactory = DBHelper.BuildConfiguration().Configure().BuildSessionFactory();
            ISession session = sessionFactory.OpenSession();
            Contracts.UserInfo u = null;
            try
            {
                u = (Contracts.UserInfo)session.CreateCriteria(typeof(Contracts.UserInfo))
                .Add(Expression.Eq("UserName", name))
                .UniqueResult();
            }
            catch (Exception ex)
            {
                throw ex;
            }

            Contracts.UserInfo newu;
            if (u != null)
            {
                newu = UserHelper.CreateUser(u);
                string dbPasswordHash = u.Password;
                string salt = dbPasswordHash.Substring(dbPasswordHash.Length - 8);
                string hashedPasswordAndSalt = UserHelper.CreatePasswordHash(password, salt);
                bool isLogin = hashedPasswordAndSalt.Equals(u.Password);
                u.IsLoggedIn = isLogin;
                if (!isLogin)
                {
                    throw new SecurityException("Password did not match");
                }
            }
            else
            {
                throw new SecurityException("User was not found");
            }

            session.Close();
            return newu;
        }

        public override void Create(Rodunu.Movies.Contracts.UserInfo identifiable)
        {
            ISessionFactory sessionFactory = DBHelper.BuildConfiguration().Configure().BuildSessionFactory();
            ISession session = sessionFactory.OpenSession();
            string salt = UserHelper.CreateSalt(SALTSIZE);
            identifiable.Password = UserHelper.CreatePasswordHash(identifiable.Password, salt);
            session.Save(identifiable);
            session.Close();
        }

        public override void Update(Rodunu.Movies.Contracts.UserInfo identifiable)
        {
            ISessionFactory sessionFactory = DBHelper.BuildConfiguration().Configure().BuildSessionFactory();
            ISession session = sessionFactory.OpenSession();
            ITransaction transaction = session.BeginTransaction();
            session.Update(identifiable);
            transaction.Commit();
            session.Close();
        }

        public UserValidation.VerificationReturnCode UpdateUserStatus(long userId, int status)
        {
            ISession session = DBHelper.GetCurrentSession();
            IQuery query = session.GetNamedQuery("UpdateUserStatus");
            query.SetInt64("UserId", userId);
            query.SetInt32("Status", status);
            try
            {
                query.UniqueResult();
                return UserValidation.VerificationReturnCode.Success;
            }
            catch (Exception)
            {
                return UserValidation.VerificationReturnCode.Failed;
            }
        }

        public void UpdateUserNetflixId(long userId, string netflixId)
        {
            ISession session = DBHelper.GetCurrentSession();
            IQuery query = session.GetNamedQuery("UpdateUserNetflixId");
            query.SetInt64("UserId", userId);
            query.SetString("NetflixId", netflixId);
            query.UniqueResult();
        }

        public UserStatusTypes.Status GetUserStatus(long userID)
        {
            ISession session = DBHelper.GetCurrentSession();
            IQuery query = session.GetNamedQuery("GetUserStatus");
            query.SetInt64("UserId", userID);
            return (UserStatusTypes.Status) query.UniqueResult();
        }

        public void SetAvatar(long userId, string avatar)
        {
            ISession session = DBHelper.GetCurrentSession();
            IQuery query = session.GetNamedQuery("SetAvatar");
            query.SetInt64("UserId", userId);
            query.SetString("Avatar", avatar);
            query.UniqueResult();
        }

        public void SetLogin(long userId)
        {
            string sqlCommand = "update UserInfo set LoggedInDate = getdate() where id = " + userId;
            ISession session = DBHelper.GetCurrentSession();
            session.CreateSQLQuery(sqlCommand).UniqueResult();
        }

        #region IUser Members


        public System.Collections.Generic.IList<Rodunu.Movies.Contracts.UserInfo> GetSharingUsers()
        {
            ISessionFactory sessionFactory = DBHelper.BuildConfiguration().Configure().BuildSessionFactory();
            ISession session = sessionFactory.OpenSession();

            System.Collections.Generic.IList<Contracts.UserInfo> users = session.CreateCriteria(typeof(Contracts.UserInfo))
                .Add(Expression.Eq("ShowProfile", true))
                .List<Contracts.UserInfo>();

            session.Close();


            return users;
        }

        #endregion

        #region IUser Members


        public Rodunu.Movies.Contracts.UserInfo GetByName(string name)
        {
            ISessionFactory sessionFactory = DBHelper.BuildConfiguration().Configure().BuildSessionFactory();
            ISession session = sessionFactory.OpenSession();

            var userInfo = (Contracts.UserInfo) session.CreateCriteria(typeof (Contracts.UserInfo))
                                                                   .Add(Expression.Eq("UserName", name)).UniqueResult();

            session.Close();


            return userInfo;
        }

        #endregion
    }
}
